package com.osmino.contacts.model.contacts;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.RawContacts;
import android.text.TextUtils;

public class ContactProviderAndroid implements IContactProvider{
	private final boolean DBG = true;
	Context context;
	
	public ContactProviderAndroid(Context context){
		this.context = context;
	}
	
	@Override
	public void add(List<IContact> contacts) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void modify(List<IContact> contacts) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void merge(List<IContact> contacts) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void delete(List<IContact> contacts) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public List<IContact> select() {

		//raw_contact table
		List<IContactBuilder> blist = new ArrayList<IContactBuilder>();
		List<IContact> clist = new ArrayList<IContact>();
		
		String[] projection = new String[]{RawContacts.CONTACT_ID, RawContacts._ID, RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_TYPE};
		Cursor c = context.getContentResolver().query(RawContacts.CONTENT_URI,
				  projection,
				  RawContacts._ID + ">0",
		          null, 
		          null
		      	);
		if(c.moveToFirst()){
			do{
				IContactBuilder cb = new ContactBuilderAndroid();
				int id = c.getInt(c.getColumnIndexOrThrow(RawContacts.CONTACT_ID));
				int rawid = c.getInt(c.getColumnIndexOrThrow(RawContacts._ID));
				String aname = c.getString(c.getColumnIndexOrThrow(RawContacts.ACCOUNT_NAME));
				String atype = c.getString(c.getColumnIndexOrThrow(RawContacts.ACCOUNT_TYPE));
				
				cb.set(IContact.ID_I, id > 0 ? id : IContact.UNDEF_I);
				cb.set(IContact.ID_RAW_I, rawid);
				cb.set(IContact.ACCOUNT_NAME_S, TextUtils.isEmpty(aname) ? IContact.UNDEF_S : aname);
				cb.set(IContact.ACCOUNT_TYPE_S, TextUtils.isEmpty(atype) ? IContact.UNDEF_S : atype);
				clist.add(cb.create());
			}
			while(c.moveToNext());
		}
		c.close();
		
		//is phone, is photo
		
		projection = new String[]{Contacts._ID, Contacts.HAS_PHONE_NUMBER, Contacts.PHOTO_ID};
		c = context.getContentResolver().query(
				  Contacts.CONTENT_URI,
				  projection,
		          Contacts._ID + ">0",
		          null, 
		          null
		      	);
		int size = clist.size();
		if(c.moveToFirst()){
			do{
				int cursorId = c.getInt(c.getColumnIndexOrThrow(Contacts._ID));
				boolean hasPhone = c.getInt(c.getColumnIndexOrThrow(Contacts.HAS_PHONE_NUMBER))>0 ? true : false;
				boolean hasPhoto = c.getInt(c.getColumnIndexOrThrow(Contacts.PHOTO_ID))> 0 ? true : false ;
				boolean found = false;
				for(int i=0;i<size;i++){
					if(clist.get(i).containsKey(IContact.ID_I)){
						int listId = clist.get(i).getData(IContact.ID_I);
						found = (cursorId == listId);
					}
					if(found){
						clist.get(i).setData(IContact.HAS_PHONE_B, hasPhone);
						clist.get(i).setData(IContact.HAS_PHOTO_B, hasPhoto);
						if(hasPhone){
							clist.get(i).setData(IContact.PHONES_H_IS, new HashMap());
						}
						if(hasPhoto){
							clist.get(i).setData(IContact.PHOTO_ID_I, c.getInt(c.getColumnIndexOrThrow(Contacts.PHOTO_ID)));
						}
						break;
					}
				}
			}
			while(c.moveToNext());
		}
		c.close();
		
		//phones && names
		
		projection = new String[]{
				Data._ID, Data.RAW_CONTACT_ID, Data.MIMETYPE, Data.IS_PRIMARY, Data.IS_SUPER_PRIMARY,
				Data. DATA1, Data. DATA2, Data. DATA3, Data. DATA4, Data. DATA5, 
				Data. DATA6, Data. DATA7, Data. DATA8, Data. DATA9, Data. DATA10, 
				Data. DATA11, Data. DATA12, Data. DATA13, Data. DATA14, Data. DATA15, 
		};
		c = context.getContentResolver().query(
				  Data.CONTENT_URI,
				  projection,
		          String.format(
		        		  "%s = \"%s\" OR %s = \"%s\"", 
		        		  Data.MIMETYPE, 
		        		  Phone.CONTENT_ITEM_TYPE, 
		        		  Data.MIMETYPE,
		        		  StructuredName.CONTENT_ITEM_TYPE
		          ),
		          null, 
		          null
		      	);
		if(c.moveToFirst()){
			do{
				int dataRawId = c.getInt(c.getColumnIndexOrThrow(Data.RAW_CONTACT_ID));
				String mimetype = c.getString(c.getColumnIndexOrThrow(Data.MIMETYPE));
				boolean found = false;
				for(int i=0;i<size;i++){
					if(clist.get(i).containsKey(IContact.ID_RAW_I)){
						int listRawId = clist.get(i).getData(IContact.ID_RAW_I);
						found = (dataRawId == listRawId);
					}
					if(!found){
						continue;
					}
					if(	mimetype.equals(CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE )){
						if(DBG)
							System.out.println("mimetype == CommonDataKinds.StructuredName.CONTENT_ITEM_TYP");
						String displayName = c.getString(c.getColumnIndexOrThrow(CommonDataKinds.StructuredName.DISPLAY_NAME));
						String givenName = c.getString(c.getColumnIndexOrThrow(CommonDataKinds.StructuredName.GIVEN_NAME));
						String familyName = c.getString(c.getColumnIndexOrThrow(CommonDataKinds.StructuredName.FAMILY_NAME));
						if(!TextUtils.isEmpty(displayName)){
							clist.get(i).setData(IContact.DISPLAY_NAME_S, displayName);
						}
						if(!TextUtils.isEmpty(givenName)){
							clist.get(i).setData(IContact.FIRST_NAME_S, givenName);
						}
						if(!TextUtils.isEmpty(familyName)){
							clist.get(i).setData(IContact.LAST_NAME_S, familyName);
						}
					}
					else if(mimetype.equals(CommonDataKinds.Phone.CONTENT_ITEM_TYPE)){
						if(DBG)
							System.out.println("mimetype == CommonDataKinds.Phone.CONTENT_ITEM_TYPE");
						int ptype = c.getInt(c.getColumnIndexOrThrow(CommonDataKinds.Phone.TYPE));
						String pnumber = c.getString(c.getColumnIndexOrThrow(CommonDataKinds.Phone.NUMBER));
						boolean isPrimary = c.getInt(c.getColumnIndexOrThrow(CommonDataKinds.Phone.IS_PRIMARY)) > 0 ? true : false ; 
						boolean isSuperPrimary = c.getInt(c.getColumnIndexOrThrow(CommonDataKinds.Phone.IS_SUPER_PRIMARY)) > 0 ? true : false ;
						if(isSuperPrimary || isPrimary){
							clist.get(i).setData(IContact.PHONE_PRI_I, ptype);
						}
						clist.get(i).getData(IContact.PHONES_H_IS, HashMap.class).put(ptype, pnumber);
					}
					else{
						if(DBG)
							System.out.println("mimetype == "+mimetype);
					}
				}
			}
			while(c.moveToNext());
		}
		c.close();
		
		//photos
		for(int i=0;i<size;i++){
			boolean hasPhoto = clist.get(i).containsKey(IContact.HAS_PHOTO_B) &&
				clist.get(i).getData(IContact.HAS_PHOTO_B, Boolean.class);
			if(hasPhoto){
				int photoId = clist.get(i).getData(IContact.PHOTO_ID_I, Integer.class);
				int contactId = clist.get(i).getData(IContact.ID_I, Integer.class);
				BitmapDrawable bd = getPhoto(context, contactId, 30, 30, Bitmap.Config.RGB_565);
				clist.get(i).setData(IContact.PHOTO_BD, bd);
			}
		}
		
		return clist;
	}

	private static BitmapDrawable getPhoto(Context context, int contactId, int w, int h, Bitmap.Config config){
		Uri photoUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
		Bitmap photoBitmap;
		ContentResolver cr = context.getContentResolver();
		InputStream is = ContactsContract.Contacts.openContactPhotoInputStream(cr, photoUri);
		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inPreferredConfig = config;
		photoBitmap = BitmapFactory.decodeStream(is, null, options);
		if(photoBitmap==null)
			return null;
		Bitmap scaled = Bitmap.createScaledBitmap(photoBitmap, w, h, true);
		photoBitmap.recycle();
		BitmapDrawable bd = new BitmapDrawable(scaled);
		return bd;
	}
}